import 'dart:async';

import 'package:camera/camera.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:google_mlkit_barcode_scanning/google_mlkit_barcode_scanning.dart';
import 'package:scanning_helper/widgets/camera_view.dart';
import 'package:scanning_helper/widgets/flashlight_button.dart';
import 'package:scanning_helper/widgets/position_view.dart';

List<CameraDescription> deviceCameras = <CameraDescription>[];

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  deviceCameras = await availableCameras();
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp]);
    SystemChrome.setEnabledSystemUIMode(SystemUiMode.edgeToEdge);
    SystemChrome.setSystemUIOverlayStyle(SystemUiOverlayStyle.light
        .copyWith(statusBarColor: Colors.transparent, systemNavigationBarColor: Colors.transparent));
    return MaterialApp(
      title: 'Flutter Scanning Helper',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const BarcodeScannerView(),
    );
  }
}

class BarcodeScannerView extends StatefulWidget {
  const BarcodeScannerView({super.key});

  @override
  State<BarcodeScannerView> createState() => _BarcodeScannerViewState();
}

class _BarcodeScannerViewState extends State<BarcodeScannerView> with SingleTickerProviderStateMixin {
  final BarcodeScanner _barcodeScanner = BarcodeScanner(formats: [BarcodeFormat.all]);

  bool isProcess = false;

  ValueNotifier<PositionData?> positionDataValue = ValueNotifier(null);

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {
    _barcodeScanner.close();
    super.dispose();
  }

  /// 图片分析处理
  Future<void> processImage(InputImage inputImage, CameraController controller) async {
    if (isProcess) return;
    isProcess = true;
    List<Barcode> barcodes = await _barcodeScanner.processImage(inputImage);
    if (inputImage.inputImageData?.size != null && inputImage.inputImageData?.imageRotation != null) {
      // 实时构建坐标
      final oldData = positionDataValue.value;
      positionDataValue.value = oldData != null
          ? oldData.copyWith(
              barcodes: barcodes,
              absoluteImageSize: inputImage.inputImageData!.size,
              rotation: inputImage.inputImageData!.imageRotation,
            )
          : PositionData(
              barcodes: barcodes,
              absoluteImageSize: inputImage.inputImageData!.size,
              rotation: inputImage.inputImageData!.imageRotation,
            );
    }
    for (Barcode barcode in barcodes) {
      print('barcode value: ${barcode.rawValue}');
    }
    final barcodesVal = barcodes.fold(<String>[], (acc, element) {
      var rawValue = element.rawValue;
      if (rawValue != null) {
        acc.add(rawValue);
      }
      return acc;
    });
    positionDataValue.value = positionDataValue.value
        ?.copyWith(barcodesVal: [...?positionDataValue.value?.barcodesVal, ...barcodesVal].toSet().toList());
    isProcess = false;
  }

  ///清除扫码结果
  void clearBarcodesVal() {
    positionDataValue.value = positionDataValue.value?.copyWith(barcodesVal: []);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      extendBodyBehindAppBar: true,
      appBar:
          AppBar(backgroundColor: Colors.transparent, elevation: 0, centerTitle: true, title: Text("扫码测试")),
      body: CameraView(
        onImage: processImage,
        builder: (context, cameraPreview, cameraController) {
          return Stack(
            fit: StackFit.expand,
            children: [
              //摄像区
              cameraPreview,
              //多码定位区
              ValueListenableBuilder(
                valueListenable: positionDataValue,
                builder: (BuildContext context, PositionData? positionData, Widget? child) {
                  return positionData == null ? SizedBox.shrink() : PositionView(barcodesData: positionData);
                },
              ),
              //防误触区(屏蔽底层事件)
              Positioned(
                bottom: 0,
                left: 0,
                right: 0,
                height: 240,
                child: AbsorbPointer(
                  child: SizedBox.expand(),
                ),
              ),
              //照明区
              Positioned(
                  bottom: 190,
                  left: 0,
                  right: 0,
                  child: Center(
                    child: FlashlightButton(cameraController: cameraController),
                  )),
              //结果区
              Positioned(
                bottom: 0,
                left: 0,
                right: 0,
                child: ValueListenableBuilder(
                  valueListenable: positionDataValue,
                  builder: (BuildContext context, PositionData? positionData, Widget? child) {
                    return Center(
                      child: SafeArea(
                        child: Padding(
                          padding: const EdgeInsets.symmetric(horizontal: 28),
                          child: GestureDetector(
                            onDoubleTap: clearBarcodesVal,
                            child: Container(
                              height: 140,
                              decoration: BoxDecoration(
                                color: Colors.white54,
                                borderRadius: const BorderRadius.all(Radius.circular(8)),
                              ),
                              child: ListView(
                                children: positionData == null
                                    ? []
                                    : positionData.barcodesVal.map((val) {
                                        return Padding(
                                          padding: const EdgeInsets.all(8.0),
                                          child: Center(child: Text(val)),
                                        );
                                      }).toList(),
                              ),
                            ),
                          ),
                        ),
                      ),
                    );
                  },
                ),
              ),
            ],
          );
        },
      ),
    );
  }
}
